﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using TestByWire.Tutorial.Domain;

namespace TestByWire.Tutorial
{
	[TestClass]
	[UseStubLateBound(typeof(IDataLayer), "_dataLayer", typeof(LateBoundDataLayerOne))]
	public class LateBoundOverrides : TestTarget<ComplexLogicLayer>
	{
		[TestMethod]
		public void MustUseLateBoundStubOne()
		{
			var id = When.Calling.Execute();

			Assert.AreEqual(LateBoundDataLayerOne.UniqueId, id);
		}

		[TestMethod]
		[UseStubLateBound(typeof(IDataLayer), "_dataLayer")]
		public void MustUseLateBoundRhinoStub()
		{
            //NOTE: This test is fishy
			Given.That<IDataLayer>("_dataLayer", x => x.Execute()).Returns("3");

			var id = When.Calling.Execute();

			Assert.AreEqual("3", id);
		}

		[TestMethod]
		[UseStubLateBound(typeof(IDataLayer), "_dataLayer", typeof(LateBoundDataLayerTwo))]
		public void MustUseLateBoundStubTwo()
		{
			var id = When.Calling.Execute();

			Assert.AreEqual(LateBoundDataLayerTwo.UniqueId, id);
		}

		[TestMethod]
		[UseStubLateBound(typeof(IDataLayer), "_dataLayer", typeof(LateBoundDataLayerTwo))]
		[UseStubLateBound(typeof(IDataLayer), "_otherDataLayer", typeof(LateBoundDataLayerOne))]
		public void MustOverrideOtherDataLayer()
		{
			var dalMsg = When.Calling.OtherExecute();

			Assert.AreEqual(LateBoundDataLayerOne.UniqueId, dalMsg);
		}

		[TestMethod]
		[UseStubLateBound(typeof(IDataLayer), "_dataLayer")]
		[UseStubLateBound(typeof(IDataLayer), "_otherDataLayer")]
		public void MustBeAbleToVerifyDataLayerCall()
		{
			When.Calling.Execute();

			Then<IDataLayer>.Should("_dataLayer",a => a.Execute());
		}

		[TestMethod]
		[UseStubLateBound(typeof(IDataLayer), "_dataLayer")]
		[UseStubLateBound(typeof(IDataLayer), "_otherDataLayer")]
		public void MustBeAbleToVerifyOtherDataLayerCall()
		{
			When.Calling.OtherExecute();

			Then<IDataLayer>.Should("_otherDataLayer", a => a.Execute());
		}
	}

	public class ComplexLogicLayer
	{
		private readonly IDataLayer _dataLayer;
		private readonly IDataLayer _otherDataLayer;

		public ComplexLogicLayer()
		{
			_dataLayer = new DataLayer();
			_otherDataLayer = new OtherDataLayer();
		}

		public string Execute()
		{
			return _dataLayer.Execute();
		}

		public string OtherExecute()
		{
			return _otherDataLayer.Execute();
		}
	}

	public class LateBoundDataLayerOne : IDataLayer
	{
		public const string UniqueId = "{5922D4C2-F320-439B-A76B-CE2F1FACA822}";

		public string Execute()
		{
			return UniqueId;
		}

		public string[] ArrayExecute()
		{
			return null;
		}
	}

	public class LateBoundDataLayerTwo : IDataLayer
	{
		public const string UniqueId = "{CFE459F0-7A69-42A5-BFB1-CDE4884D4C62}";

		public string Execute()
		{
			return UniqueId;
		}

		public string[] ArrayExecute()
		{
			return null;
		}
	}
}
